﻿<!DOCTYPE html>
<html lang="en">

<head>
    <link href="https://atlas.microsoft.com/sdk/javascript/mapcontrol/2/atlas.min.css" rel="stylesheet" />
    <script src="https://atlas.microsoft.com/sdk/javascript/mapcontrol/2/atlas.min.js"></script>
    <script src="https://atlas.microsoft.com/sdk/javascript/service/2/atlas-service.min.js"></script>
    <script>
    /*
    This module contains the HtmlMarkerLayer class, which is a layer that renders HTML markers on the map.
    Source: https://learn.microsoft.com/en-us/samples/azure-samples/azure-maps-html-marker-layer/azure-maps-html-marker-layer-module/

    azure-maps-html-marker-layer Version: 0.0.1
    MIT License - Copyright (c) Microsoft Corporation.
    */
    
    !function(e, y) {
        "use strict";
        var o = function(e, t) {
            return (o = Object.setPrototypeOf || {
                __proto__: []
            }instanceof Array && function(e, t) {
                e.__proto__ = t
            }
            || function(e, t) {
                for (var r in t)
                    t.hasOwnProperty(r) && (e[r] = t[r])
            }
            )(e, t)
        };
        function t(e, t) {
            function r() {
                this.constructor = e
            }
            o(e, t),
            e.prototype = null === t ? Object.create(t) : (r.prototype = t.prototype,
            new r)
        }
        var n = function() {
            return (n = Object.assign || function(e) {
                for (var t, r = 1, o = arguments.length; r < o; r++)
                    for (var a in t = arguments[r])
                        Object.prototype.hasOwnProperty.call(t, a) && (e[a] = t[a]);
                return e
            }
            ).apply(this, arguments)
        };
        function a(e, n, s, l) {
            return new (s = s || Promise)(function(r, t) {
                function o(e) {
                    try {
                        i(l.next(e))
                    } catch (e) {
                        t(e)
                    }
                }
                function a(e) {
                    try {
                        i(l.throw(e))
                    } catch (e) {
                        t(e)
                    }
                }
                function i(e) {
                    var t;
                    e.done ? r(e.value) : ((t = e.value)instanceof s ? t : new s(function(e) {
                        e(t)
                    }
                    )).then(o, a)
                }
                i((l = l.apply(e, n || [])).next())
            }
            )
        }
        function g(r, o) {
            var a, i, n, e, s = {
                label: 0,
                sent: function() {
                    if (1 & n[0])
                        throw n[1];
                    return n[1]
                },
                trys: [],
                ops: []
            };
            return e = {
                next: t(0),
                throw: t(1),
                return: t(2)
            },
            "function" == typeof Symbol && (e[Symbol.iterator] = function() {
                return this
            }
            ),
            e;
            function t(t) {
                return function(e) {
                    return function(t) {
                        if (a)
                            throw new TypeError("Generator is already executing.");
                        for (; s; )
                            try {
                                if (a = 1,
                                i && (n = 2 & t[0] ? i.return : t[0] ? i.throw || ((n = i.return) && n.call(i),
                                0) : i.next) && !(n = n.call(i, t[1])).done)
                                    return n;
                                switch (i = 0,
                                n && (t = [2 & t[0], n.value]),
                                t[0]) {
                                case 0:
                                case 1:
                                    n = t;
                                    break;
                                case 4:
                                    return s.label++,
                                    {
                                        value: t[1],
                                        done: !1
                                    };
                                case 5:
                                    s.label++,
                                    i = t[1],
                                    t = [0];
                                    continue;
                                case 7:
                                    t = s.ops.pop(),
                                    s.trys.pop();
                                    continue;
                                default:
                                    if (!(n = 0 < (n = s.trys).length && n[n.length - 1]) && (6 === t[0] || 2 === t[0])) {
                                        s = 0;
                                        continue
                                    }
                                    if (3 === t[0] && (!n || t[1] > n[0] && t[1] < n[3])) {
                                        s.label = t[1];
                                        break
                                    }
                                    if (6 === t[0] && s.label < n[1]) {
                                        s.label = n[1],
                                        n = t;
                                        break
                                    }
                                    if (n && s.label < n[2]) {
                                        s.label = n[2],
                                        s.ops.push(t);
                                        break
                                    }
                                    n[2] && s.ops.pop(),
                                    s.trys.pop();
                                    continue
                                }
                                t = o.call(r, s)
                            } catch (e) {
                                t = [6, e],
                                i = 0
                            } finally {
                                a = n = 0
                            }
                        if (5 & t[0])
                            throw t[1];
                        return {
                            value: t[0] ? t[1] : void 0,
                            done: !0
                        }
                    }([t, e])
                }
            }
        }
        var r = (i.merge = function(e, t) {
            for (var r = window || global, o = 0, a = e.split("."); o < a.length; o++) {
                var i = a[o];
                if (!r[i])
                    return t;
                r = r[i]
            }
            return n(n({}, r), t)
        }
        ,
        i);
        function i() {}
        var s, l = (t(u, s = y.layer.BubbleLayer),
        u.prototype.getOptions = function() {
            return Object.assign({}, this._options)
        }
        ,
        u.prototype.setOptions = function(e) {
            var t = this._options
              , r = {}
              , o = !1;
            e.source && t.source !== e.source && (t.source = e.source,
            r.source = e.source,
            o = !0),
            e.sourceLayer && t.sourceLayer !== e.sourceLayer && (t.sourceLayer = e.sourceLayer,
            r.sourceLayer = e.sourceLayer,
            o = !0),
            e.filter && t.filter !== e.filter && (t.filter = e.filter,
            r.filter = e.filter,
            o = !0),
            "number" == typeof e.minZoom && t.minZoom !== e.minZoom && (t.minZoom = e.minZoom,
            r.minZoom = e.minZoom),
            "number" == typeof e.maxZoom && t.maxZoom !== e.maxZoom && (t.maxZoom = e.maxZoom,
            r.maxZoom = e.maxZoom),
            void 0 !== e.visible && t.visible !== e.visible && (t.visible = e.visible,
            r.visible = e.visible),
            e.markerCallback && t.markerCallback != e.markerCallback && (t.markerCallback = e.markerCallback,
            o = !0),
            "boolean" == typeof e.updateWhileMoving && t.updateWhileMoving !== e.updateWhileMoving && (t.updateWhileMoving = e.updateWhileMoving),
            o ? this._clearCache(!0) : this._updateMarkers(),
            s.prototype.setOptions.call(this, r)
        }
        ,
        u.prototype.update = function() {
            this._clearCache(!0),
            this._updateMarkers()
        }
        ,
        u.prototype.onAdd = function(e) {
            var t = this
              , r = e.events;
            e && (r.remove("moveend", t._updateMarkers),
            r.remove("move", t._mapMoved),
            r.remove("sourcedata", t._sourceUpdated)),
            (r = (t._map = e).events).add("moveend", t._updateMarkers),
            r.add("move", t._mapMoved),
            r.add("sourcedata", t._sourceUpdated),
            s.prototype.onAdd.call(this, e)
        }
        ,
        u.prototype.onRemove = function() {
            var e = this
              , t = e._map;
            if (t) {
                var r = t.events;
                r.remove("moveend", e._updateMarkers),
                r.remove("move", e._mapMoved),
                r.remove("sourcedata", e._sourceUpdated)
            }
            e._clearCache(!1),
            e._map = null,
            s.prototype.onRemove.call(this)
        }
        ,
        u.prototype._getSourceClass = function() {
            var e = this.getSource();
            return "string" == typeof e && null !== this._map ? this._map.sources.getById(e) : e instanceof y.source.Source ? e : null
        }
        ,
        u.prototype._clearCache = function(e) {
            var t = this;
            if (t._markerCache = {},
            t._map)
                for (var r = 0, o = t._markers.length; r < o; r++) {
                    var a = t._markers[r];
                    t._removeEvents(a),
                    a._eventsAttached = !1,
                    t._map.markers.remove(a)
                }
            t._markers = [],
            t._markerIds = [],
            e && t._updateMarkers()
        }
        ,
        u.prototype._getMarker = function(o, a, i) {
            var n = this
              , s = n._markerCache
              , e = n._options;
            if (o = o || a.join(",") + JSON.stringify(i || {}),
            s[o])
                return s[o];
            var t = e.markerCallback(o, a, i);
            if (!(t instanceof y.HtmlMarker))
                return new Promise(function(r) {
                    t.then(function(e) {
                        var t = n._getExtendedMarker(e, o, a, i);
                        t && (s[o] = t,
                        r(t))
                    })
                }
                );
            var r = n._getExtendedMarker(t, o, a, i);
            return r ? (s[o] = r,
            Promise.resolve(r)) : null
        }
        ,
        u.prototype._getExtendedMarker = function(e, t, r, o) {
            var a = e;
            return a ? (a.properties = o,
            a.id = t,
            a.setOptions({
                position: r
            }),
            a) : null
        }
        ,
        u.prototype._addEvents = function(t) {
            var r = this;
            r._supportedEvents.forEach(function(e) {
                r.map.events.add(e, t, r._wrappedEvent)
            })
        }
        ,
        u.prototype._removeEvents = function(t) {
            var r = this;
            r._supportedEvents.forEach(function(e) {
                r.map.events.remove(e, t, r._wrappedEvent)
            })
        }
        ,
        u);
        function u(e, t, r) {
            var o = s.call(this, e, t) || this;
            return o._options = {
                minZoom: 0,
                maxZoom: 24,
                visible: !0,
                updateWhileMoving: !1,
                filter: ["==", ["geometry-type"], "Point"],
                markerCallback: function(e, t, r) {
                    return r.cluster ? new y.HtmlMarker({
                        position: t,
                        text: r.point_count_abbreviated
                    }) : new y.HtmlMarker({
                        position: t
                    })
                }
            },
            o._markers = [],
            o._markerIds = [],
            o._markerCache = {},
            o._supportedEvents = ["click", "contextmenu", "dblclick", "drag", "dragstart", "dragend", "keydown", "keypress", "keyup", "mousedown", "mouseenter", "mouseleave", "mousemove", "mouseout", "mouseover", "mouseup"],
            o._mapMoved = function() {
                o._options.updateWhileMoving && o._updateMarkers()
            }
            ,
            o._sourceUpdated = function(e) {
                var t = o._getSourceClass();
                t && t.getId() === e.source.id && (o._timer && clearTimeout(o._timer),
                o._timer = setTimeout(o._sourceUpdater, 33))
            }
            ,
            o._sourceUpdater = function() {
                o._timer = null,
                o._clearCache(!0)
            }
            ,
            o._updateMarkers = function() {
                return a(o, void 0, void 0, function() {
                    var t, r, o, a, i, n, s, l, u, c, p, d, m, h, f, v, _, k;
                    return g(this, function(e) {
                        switch (e.label) {
                        case 0:
                            if (r = (t = this)._map,
                            o = t._markers,
                            a = t._options,
                            i = r ? r.getCamera().zoom : void 0,
                            !(a.visible && void 0 !== i && i >= a.minZoom && i <= a.maxZoom))
                                return [3, 5];
                            n = t.getSource(),
                            s = "string" == typeof n ? n : n.getId(),
                            l = r.map.querySourceFeatures(s, {
                                sourceLayer: t.getOptions().sourceLayer,
                                filter: a.filter
                            }),
                            u = [],
                            c = [],
                            v = f = h = m = d = p = void 0,
                            k = 0,
                            _ = l.length,
                            e.label = 1;
                        case 1:
                            return k < _ ? (p = v = null,
                            l[k]instanceof y.Shape ? "Point" === (h = l[k]).getType() && (m = h.getCoordinates(),
                            d = h.getProperties(),
                            p = h.getId()) : "Point" === (f = l[k]).geometry.type && (m = f.geometry.coordinates,
                            (d = f.properties) && d.cluster ? p = "cluster_" + f.properties.cluster_id : f.id && (p = f.id)),
                            m ? [4, t._getMarker(p, m, d)] : [3, 3]) : [3, 4];
                        case 2:
                            (v = e.sent())._eventsAttached || (t._addEvents(v),
                            v._eventsAttached = !0),
                            v && (v.id && c.push(v.id),
                            v.id && -1 !== t._markerIds.indexOf(v.id) || (u.push(v),
                            r.markers.add(v))),
                            e.label = 3;
                        case 3:
                            return k++,
                            [3, 1];
                        case 4:
                            for (k = o.length - 1; 0 <= k; k--)
                                o[k].id && -1 !== c.indexOf(o[k].id) || (r.markers.remove(o[k]),
                                o.splice(k, 1));
                            return t._markers = o.concat(u),
                            t._markerIds = c,
                            [3, 6];
                        case 5:
                            0 < t._markers.length && (r.markers.remove(t._markers),
                            t._markers = []),
                            e.label = 6;
                        case 6:
                            return [2]
                        }
                    })
                })
            }
            ,
            o._wrappedEvent = function(e) {
                o.map.events.invoke(e.type, o, e)
            }
            ,
            s.prototype.setOptions.call(o, {
                color: "transparent",
                radius: 0,
                strokeWidth: 0
            }),
            o.setOptions(r || {}),
            o
        }
        var b, c = Object.freeze({
            __proto__: null,
            HtmlMarkerLayer: l
        }), p = (t(C, b = y.HtmlMarker),
        C.prototype.getTotalValue = function() {
            return this._total
        }
        ,
        C.prototype.getSliceValue = function(e) {
            var t = this._options.values;
            return 0 <= e && e < t.length ? t[e] : 0
        }
        ,
        C.prototype.getSlicePercentage = function(e) {
            return 0 < this._total ? Math.round(this.getSliceValue(e) / this._total * 1e4) / 100 : 0
        }
        ,
        C.prototype.getOptions = function() {
            return Object.assign({}, b.prototype.getOptions.call(this), this._options)
        }
        ,
        C.prototype.setOptions = function(e) {
            var t = this._options
              , r = JSON.stringify
              , o = !1;
            e.radius && 0 < e.radius && e.radius != t.radius && (t.radius = e.radius,
            o = !0),
            0 <= e.innerRadius && e.innerRadius != t.innerRadius && (t.innerRadius = e.innerRadius,
            o = !0),
            e.colors && r(e.colors) !== r(t.colors) && (t.colors = e.colors,
            o = !0),
            e.fillColor && r(e.fillColor) !== r(t.fillColor) && (t.fillColor = e.fillColor,
            o = !0),
            e.strokeColor && e.strokeColor !== t.strokeColor && (t.strokeColor = e.strokeColor,
            o = !0),
            0 <= e.strokeWidth && e.strokeWidth != t.strokeWidth && (t.strokeWidth = e.strokeWidth,
            o = !0),
            void 0 !== e.tooltipCallback && t.tooltipCallback != e.tooltipCallback && (t.tooltipCallback = e.tooltipCallback,
            o = !0),
            e.values && r(e.values) !== r(t.values) && (t.values = e.values,
            o = !0),
            void 0 !== e.text && e.text !== t.text && (b.prototype.setOptions.call(this, {
                text: e.text
            }),
            o = !0),
            void 0 !== e.textClassName && e.textClassName !== t.textClassName && (t.textClassName = e.textClassName,
            o = !0),
            o && this._render(),
            b.prototype.setOptions.call(this, e)
        }
        ,
        C.prototype._render = function() {
            var e = this
              , t = e._options
              , r = t.values
              , o = t.radius
              , a = 0
              , i = 0;
            if (r) {
                e._total = r.reduce(function(e, t) {
                    return e + t
                }, 0);
                for (var n = C._moreColors, s = Math.random, l = Math.round, u = 0; r.length > t.colors.length; )
                    n.length < r.length && n.push("hsl(" + l(360 * s()) + "," + (l(20 * s()) + 70) + "%," + (l(40 * s()) + 30) + "%)"),
                    t.colors.push(n[u]),
                    u++;
                var c = o + t.strokeWidth
                  , p = ['<svg xmlns="http://www.w3.org/2000/svg" width="' + 2 * c + 'px" height="' + 2 * c + 'px">']
                  , d = ""
                  , m = void 0;
                if (0 < t.innerRadius && t.innerRadius <= t.radius && (m = "piechart-innercircle-" + l(1e7 * s()),
                p.push('<defs><mask id="' + m + '"><rect width="100%" height="100%" fill="white"/><circle r="' + t.innerRadius + '" cx="' + c + '" cy="' + c + '" fill="black"/></mask></defs>\n                    <circle r="' + t.innerRadius + '" cx="' + c + '" cy="' + c + '" style="fill:' + t.fillColor + ";stroke:" + t.strokeColor + ";stroke-width:" + 2 * t.strokeWidth + 'px;"/>')),
                0 < e._total)
                    for (var h = t.tooltipCallback, f = 2 * Math.PI / e._total, v = 0; v < r.length; v++) {
                        i = f * r[v],
                        h && (d = h(e, v));
                        var _ = v < t.colors.length ? t.colors[v] : n[v];
                        p.push(e._createSlice(c, c, o, a, i, _, d, m)),
                        a += i
                    }
                var k = e.getOptions().text;
                k && p.push('<text x="' + c + '" y="' + (c + 7) + '" style="font-size:16px;font-family:arial;fill:#000;font-weight:bold;" class="' + (t.textClassName || "") + '" text-anchor="middle">' + k + "</text>"),
                p.push("</svg>"),
                b.prototype.getOptions.call(this).htmlContent.innerHTML = p.join("")
            }
        }
        ,
        C.prototype._createSlice = function(e, t, r, o, a, i, n, s) {
            var l = this._options
              , u = Math.PI
              , c = "";
            if (s && (c = ' mask="url(#' + s + '"'),
            2 * u * .99 < a)
                return '<circle r="' + r + '" cx="' + e + '" cy="' + t + '" style="fill:' + i + ";stroke:" + l.strokeColor + ";stroke-width:" + l.strokeWidth + 'px;"' + c + "><title>" + n + "</title></circle>";
            var p = Math.sin
              , d = Math.cos
              , m = e + r * p(o)
              , h = t - r * d(o)
              , f = e + r * p(o + a)
              , v = t - r * d(o + a)
              , _ = (l.innerRadius,
            p(o),
            l.innerRadius,
            d(o),
            l.innerRadius,
            p(o + a),
            l.innerRadius,
            d(o + a),
            0);
            return u < a && (_ = 1),
            '<path d="M' + e + " " + t + " L " + m + " " + h + " A " + r + "," + r + " 0 " + _ + " 1 " + f + " " + v + 'z" style="fill:' + i + ";stroke:" + l.strokeColor + ";stroke-width:" + l.strokeWidth + 'px;"' + c + "><title>" + n + "</title></path>"
        }
        ,
        C._moreColors = [],
        C);
        function C(e) {
            var t = b.call(this, e) || this;
            return t._options = {
                values: [],
                radius: 40,
                colors: ["#d7191c", "#fdae61", "#ffffbf", "#abdda4", "#2b83ba"],
                fillColor: "transparent",
                strokeWidth: 0,
                strokeColor: "#666666",
                innerRadius: 0
            },
            t._total = 0,
            t.properties = {},
            b.prototype.setOptions.call(t, {
                htmlContent: document.createElement("div"),
                pixelOffset: [0, 0],
                anchor: "center"
            }),
            t.setOptions(e),
            t
        }
        var d = r.merge("atlas.layer", c);
        e.PieChartMarker = p,
        e.layer = d
    }(this.atlas = this.atlas || {}, atlas);
    </script>
</head>

<style>
    html,
    body {
        width: 100%;
        height: 100%;
        padding: 0;
        margin: 0;
        overflow: hidden;
        font-family: segoeui;
    }

    #mapContainer {
        position: relative;
        width: 100%;
        height: 100%;
    }
</style>

<body>
    <div id="mapContainer"></div>

    <script>
        var map;
        var symbolLayers = [];
        var layersData = {};
        var pointsData = {};
        var dataSource;
        var id = 1;
        var controls = [];

        function initializeMap(longitude, latitude, mapServiceToken) {
            try {
                //Initialize a map instance.
                map = new atlas.Map('mapContainer', {
                    center: [longitude, latitude],
                    zoom: 3,
                    view: 'Auto',

                    //Add authentication details for connecting to Azure Maps.
                    // Note: an invalid token doesn't seem to throw any errors.
                    authOptions: {
                        authType: 'subscriptionKey',
                        subscriptionKey: mapServiceToken
                    }
                });

                map.events.add('ready', function () {
                    dataSource = new atlas.source.DataSource();
                    map.sources.add(dataSource);
                });
            }
            catch (error) {
                sendErrorInfo(error);
            }
        }

        function addSymbolLayer() {
            try {
                var layerSource = new atlas.source.DataSource();
                var newLayer = new atlas.layer.HtmlMarkerLayer(layerSource, null, {
                    markerCallback: (id, position, properties) => {
                        const pin = new atlas.HtmlMarker({
                            position: position,
                            id: id
                        });
                        pin.getElement().setAttribute('tabindex', 0);
                        return pin;
                    }
                });

                layersData[newLayer.getId()] = layerSource;
                pointsData[newLayer.getId()] = {};
                symbolLayers.push(newLayer);

                map.events.add('ready', function () {
                    map.sources.add(layerSource);
                    map.layers.add(newLayer);
                    map.events.add('click', newLayer, sendPushpinClickInfo);
                });

            }
            catch (error) {
                sendErrorInfo(error);
            }
            return newLayer.getId();
        }

        function addPoint(longitude, latitude, layerId) {
            var point = new atlas.data.Feature(new atlas.data.Point([longitude, latitude]), {name: 'MapElement'}, id);
            id++;
            try {
                map.events.add('ready', function () {
                    layersData[layerId].add([point]);
                    pointsData[layerId][point.id] = point;
                });
            }
            catch (error) {
                sendErrorInfo(error);
            }

            return point.id;
        }

        function updatePoint(longitude, latitude, pointId, layerId) {
            try {
                map.events.add('ready', function () {
                    pointsData[layerId][pointId].setCoordinates([longitude, latitude]);

                    logSymbolLayers();
                });
            }
            catch (error) {
                sendErrorInfo(error);
            }
        }

        function removePoint(pointId, layerId) {
            try {
                map.events.add('ready', function() {
                    layersData[layerId].remove(pointsData[layerId][pointId]);
                    delete pointsData[layerId][pointId];
                });
            }
            catch (error) {
                sendErrorInfo(error);
            }
        }

        function clearLayer(layerId) {
            try {
                map.events.add( 'ready', function() {
                    layersData[layerId].clear();
                    pointsData[layerId] = {};
                });
            }
            catch (error) {
                sendErrorInfo(error);
            }
        }

        function clearMap() {
            try {
                map.events.add( 'ready', function() {
                    symbolLayers = [];
                    layersData = {};
                    pointsData = {};
                });
            }
            catch (error) {
                sendErrorInfo(error);
            }
        }

        function interactiveControlsVisible(enable) {
            if (enable) {
                controls = [
                    new atlas.control.ZoomControl(),
                    new atlas.control.CompassControl(),
                    new atlas.control.PitchControl(),
                    new atlas.control.StyleControl()
                ]
                map.controls.add(controls, {
                    position: "top-right"
                });
            } else {
                map.controls.remove(controls);
                controls = [];
            }
        }

        function updateCenter(latitude, longitude) {
            try {
                map.setCamera({
                    center: [longitude, latitude]
                });
            }
            catch (error) {
                sendErrorInfo(error);
            }
        }

        function updateZoom(level) {
            try {
                map.setCamera({
                    zoom: level
                });
            }
            catch (error) {
                sendErrorInfo(error);
            }
        }

        function updateMapServiceToken(mapServiceToken) {
            try {
                clearMap();
                var location = map.getCamera().center;
                longitude = location[0];
                latitude = location[1];
                // create a new map with the new API key
                initializeMap(longitude, latitude, mapServiceToken);
            } catch (error) {
                sendErrorInfo(error);
            }
        }

        function sendPushpinClickInfo(e) {
            try {
                const latitude = e.target.options.position[0];
                const longitude = e.target.options.position[1];
                const pointClicked = e.target.id || 'Unknown';

                const coordinate = {
                    latitude,
                    longitude,
                };

                const message = {
                    type: 'pushpinClickEvent',
                    coordinate,
                    layer: 0,
                    point: pointClicked,
                    text: 'Pushpin clicked!',
                };

                console.log('Sending message:', message);
                window.chrome.webview.postMessage(message);
            } catch (error) {
                sendErrorInfo(error);
            }
        }

        function getMapLayers() {
            try {
                layers = map.layers.getLayers();
                console.log("Number of layers: " + layers.length + "\n");
                // print out the name and type of each layer
                for (var i = 0; i < layers.length; i++) {
                    if (layers[i] instanceof atlas.layer.SymbolLayer) {
                        console.log(layers[i].getId() + " is a SymbolLayer\n");
                        console.log("Source: " + layers[i].getSource() + "\n");
                    }
                }
            }
            catch (error) {
                sendErrorInfo(error);
            }
        }

        function logSymbolLayers() {
            try {
                // print out each symbolLayer in symbolLayers by id
                console.log("Number of symbol layers: " + symbolLayers.length + "\n");
                for (var i = 0; i < symbolLayers.length; i++) {
                    console.log("Id: " + symbolLayers[i].getId() + "\n");
                }
            }
            catch (error) {
                sendErrorInfo(error);
            }
        }

        function getSymbolLayers() {
            return symbolLayers;
        }

        function sendErrorInfo(e) {
            console.log(e);
            const coordinate = {
                "latitude": 0,
                "longitude": 0,
            }

            const message = {
                "type": "javascriptError",
                "coordinate": coordinate,
                "text": e.stack
            };

            window.chrome.webview.postMessage(message);
        }

    </script>
</body>

</html>